package org.qloudgen.borg;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.wicket.Session;
import org.apache.wicket.request.component.IRequestablePage;

import org.qloudgen.borg.beans.Dict;
import org.qloudgen.borg.messaging.HornetqJmsClient;
import org.qloudgen.borg.metadb.DefaultImpl;
import org.qloudgen.borg.metadb.MyBatisUtil;
import org.qloudgen.borg.pages.ClusterListPage;
import org.qloudgen.borg.pages.ClusterModifyPage;
import org.qloudgen.borg.pages.ClusterNodePage;
import org.qloudgen.borg.security.DilithiumSession;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public final class CommonValues {
	
	static Log log = LogFactory.getLog(CommonValues.class);
	
	public static boolean initFlag = false;

	private final static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
	
	public static Properties props;
	public static String osType;
	public static SqlSessionFactory factory;
	public static Runtime runtime = Runtime.getRuntime();
	public static HornetqJmsClient sender;
	public static Map<String,Class<? extends IRequestablePage>> pages = Maps.newHashMap();
	public static Map<String,String> statusNames = Maps.newHashMap();
	public static Map<String,String> taskStatusNames = Maps.newHashMap();
	public static Map<String,String> booleanNames = Maps.newHashMap();
	public static List<String> dateFormats = Lists.newArrayList();
	public static Map<String,String> isOrders = Maps.newHashMap();
	public static Map<String,String> userTypeNames = Maps.newHashMap();
	public static Map<Integer,String> paramTypes = Maps.newHashMap();
	public static Map<String,Integer> clusterOperators = Maps.newHashMap();
	public static List<String> hadoopVersions = Lists.newArrayList();

	public static Map<String,Map<String,String>> dicts = Maps.newHashMap();

	// default values
	public static final int LIST_REFRESH_TIME = 5;
	public static final int SHOW_LIST_NUMBER = 10;
	public static final int SHOW_LIST_LARGE_NUMBER = 20;
	public static final String DEFAULT_USER_PASSWORD = "123";
	public static final int DEFAULT_USER_TASK_NUMBER = 1;
	public static final String DEFAULT_HADOOP_SCRIPT_PATH = "/home/hadoop/scripts";
	public static final String DEFAULT_HADDOP_DATA_PATH = "/home/hadoop/data";
	public static final String DEFAULT_HADDOP_JAR_PATH = "/home/hadoop/jars";
	public static final String DEFAULT_FUNC_PARAM_DILIMTER = "[##]";
	public static final long DEFAULT_SLEEP_TIME = 1;
	public static final long DEFAULT_TEST_SLEEP_TIME = 5;
	public static final int DEFAULT_LIMIT_ROWS = 100;
	public static final int DEFAULT_CLEAR_DAYS = 2;
	public static final String DEFAULT_RESULT_READER = "org.qloudgen.borg.result.HiveReader";

	public static final int DEFAULT_EXCEL_LIMIT = 60000;
	public static final String DEFAULT_EXPORT_DIR= "c:\\temp";
	
	// status
	public static final String STATUS_ON = "on";
	public static final String STATUS_OFF = "off";
	public static final String STATUS_CREATE = "create";
	public static final String STATUS_UPLOAD = "upload";
	public static final String STATUS_INIT = "init";
	public static final String STATUS_PAUSE = "pause";
	public static final String STATUS_NORMAL = "normal";
	
	// task status
	public static final String TASK_STATUS_INQUEUE = "inqueue";
	public static final String TASK_STATUS_OUTQUEUE = "outqueue";
	public static final String TASK_STATUS_RUNNING = "running";
	public static final String TASK_STATUS_LOADED = "loaded";
	public static final String TASK_STATUS_TRANSFORMED = "transformed";
	public static final String TASK_STATUS_SUCCESS = "success";
	public static final String TASK_STATUS_FAILED= "failed";
	
	// rights
	public static final String RIGHT_MENU = "menu";
	public static final String RIGHT_APP = "app";
	public static final String RIGHT_FUNC = "func";
	
	// user type
	public static final String USER_TYPE_ADMIN = "admin";
	public static final String USER_TYPE_COMMON = "common";
	
	// error 
	public static final String ERROR_LOGIN = "用户不存在或密码不正确!";
	public static final String ERROR_LOGIN_USER_PAUSED = "用户暂时停止使用!";
	public static final String ERROR_OLD_PASSWORD = "旧密码输入错误!";
	public static final String ERROR_TWO_PASSWORDS_MISMATCHER = "两次新密码不一致!";
	public static final String ERROR_SAME_PASSWORDS = "新密码和旧密码相同!";
	public static final String ERROR_CREATE_USER = "用户已存在!";
	public static final String ERROR_IP_FORMAT = ". 不正确的ip!";
	public static final String ERROR_IP_PING = ". ip地址ping不通!";
	public static final String ERROR_UPLOAD_FILE = "上传文件失败!";
	public static final String ERROR_INIT = "功能初始化失败，没有创建表!";

	// info
	public static final String INFO_NO_SELECT ="请先选择!";
	public static final String INFO_CLUSTER_RUNNING = " 已经运行!";
	public static final String INFO_CLUSTER_STOPPED = " 已经停止!";
	public static final String INFO_CLUSTER_NOT_DELETED = " 运行中，不能删除!";
	public static final String INFO_NO_NODES = "请选择节点!";
	public static final String INFO_CLUSTER_RUN = "集群必须运行,才能操作!";
	public static final String INFO_UPLOAD_COMPLETED = "成功上传文件至";
	public static final String INFO_CREATE_COMPLETED = "成功创建表!";
	public static final String INFO_APP_NO_CLUSTER = "该应用没有配置可用的运行环境，无法上传文件!";
	public static final String INFO_CAN_NOT_DELETED = "不能删除!";
	public static final String INFO_CAN_NOT_PAUSED = "不能暂停!";
	public static final String INFO_NO_USER = "没有选择用户!";
	public static final String INFO_NO_FILE = "请选择文件!";
	public static final String INFO_FUNC_PARAMS_ALL_SELECT = "功能的所有参数必须选择，并赋值！";
	public static final String INFO_TASK_NO_DATA = "任务没有结果数据！";
	public static final String INFO_NOT_NULL = "有必输项未填写!";
	public static final String INFO_FUNC_NOT_PARAMS = "功能没有定义参数!";
	public static final String INFO_FUNC_NOT_RESULT = "功能没有定义结果表字段!";
	public static final String INFO_NOT_REPEAT_CLICK = "已经在处理，不要重复点击!";
	public static final String INFO_NOT_UPLOAD = "只有上传之后才能创建表!";
	public static final String INFO_SELECT_FILE = "选择上传文件";
	public static final String INFO_SAME_TASK = "有相同的查询正在运行中，请等候！";
	public static final String INFO_CAN_NOT_RELOADED = "该功能相同数据源的任务在该集群上运行！请稍后再提交。";
	public static final String INFO_EXISTS_RELOAD_TASK = "有数据重新加载任务在运行！请稍后再提交。";
	public static final String INFO_CLUSTER_PASSWORD_INCORRECT = "集群用户名或密码不正确!";
	public static final String INFO_CLEAR_LOG = "清理日志完成！";
	
	// cluster operation
	public static final String CLUSTER_START = "start";
	public static final String CLUSTER_PAUSE = "pause";
	public static final String CLUSTER_STOP = "stop";
	public static final String CLUSTER_DELETE = "delete";
	public static final String CLUSTER_REMOVE_NODE = "remove";
	public static final String CLUSTER_ADD_NODE = "add";
	public static final String CLUSTER_UPLOAD_JAR = "uploadJar";
	public static final String CLUSTER_MODIFY = "modify";
	
	// file info 
	public static final String FUNC_TABLE_PERFIX = "func_table";
	public static final String SCRIPT_SUFFIX = ".sh";
	public static final String FUNC_HANDLER_PERFIX = "func_handler";
	public static final String DS_TABLE_PERFIX = "ds_table";
	public static final String DS_LOAD_PERFIX = "ds_load";
	public static final String DS_TRANSFORM_PERFIX = "ds_transform";
	
	// shell
	public static final String RESOURCE = System.getProperty("user.dir") + "/src/main/resources";
    public static final String SHELL = RESOURCE + "/shell";
	public static final String CHECK_SUPERUSER_SH = SHELL + "/check_superuser.sh";
	public static final String CHECK_OTHER_SUPERUSER_SH = SHELL + "/check_other_superuser.sh";
	public static final String CHECK_PASSWORD_SH = SHELL + "/check_password.sh";    
	public static final String CREATE_SUPERUSER_SH = SHELL + "/create_superuser.sh";
	public static final String CONSTRUCT_ISA_LOCAL = SHELL + "/construct_isa_ssh.sh";
	public static final String OPERATOR_SH = SHELL + "/cluster_operator.sh";
	public static final String SCP_FILE_SH = SHELL + "/scpFile.sh";
	
	// osType
	public static final String OSTYPE_WINDOWS = "windows";
	public static final String OSTYPE_LINUX = "linux";
	
	private CommonValues(){};
	
	private static CommonValues commonValues = new CommonValues();

	public static CommonValues getInstance(){
		return commonValues;
	}
	
	public static String getTime(){
		return df.format(new Date());
	}
	
	private void  loadProperties()  {
	    
		CommonValues.props = new Properties();  
		
	    ClassLoader loader = getClass().getClassLoader();
		try {
			
			InputStream in = loader.getResourceAsStream("conf.properties");
			CommonValues.props.load(in);
			
		} catch (IOException e) {
			log.error(e.getMessage());
		}
	} 
	
	private void  checkProperties() throws Exception  {
	    
		String error;
		String dir = CommonValues.props.getProperty("tempdir");
		if (dir == null) {
			error = "tempdir can not be set in conf.properties";
			log.error(error);
			throwException(error);
		}
		
		File file = new File(dir);
		
		if (!file.exists()) {
			error = "tempdir : " + dir + " does not exist on OS";
			log.error(error);
			throwException(error);
		}
		
		CommonValues.osType = dir.contains(":")?CommonValues.OSTYPE_WINDOWS:CommonValues.OSTYPE_LINUX;

		
	} 
	
	public void init(){
		
		if (!CommonValues.initFlag) {
			
			try {
				CommonValues.getInstance().setCommonValues();
			} catch (Exception e) {
				log.error(e.getMessage());
				log.error("Failed in loading Common values");
				System.exit(-1);
			}
			
		}
	}
	
	private void setCommonValues() throws Exception{
		
		loadProperties();	
		
		checkProperties();
		
		CommonValues.factory = MyBatisUtil.getSqlSessionFactory();
	 			
		// get dicts
//		construct_dicts(CommonValues.dicts);

		CommonValues.pages.put(CommonValues.CLUSTER_START, ClusterListPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_PAUSE, ClusterListPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_STOP, ClusterListPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_DELETE, ClusterListPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_ADD_NODE, ClusterNodePage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_REMOVE_NODE, ClusterNodePage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_UPLOAD_JAR, ClusterListPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_MODIFY, ClusterModifyPage.class);
		
		CommonValues.statusNames.put(CommonValues.STATUS_ON, "运行中");
		CommonValues.statusNames.put(CommonValues.STATUS_OFF, "停止");
		CommonValues.statusNames.put(CommonValues.STATUS_CREATE, "已创建");
		CommonValues.statusNames.put(CommonValues.STATUS_UPLOAD, "已上传");
		CommonValues.statusNames.put(CommonValues.STATUS_INIT, "可以使用");
		CommonValues.statusNames.put(CommonValues.STATUS_NORMAL, "正常");
		CommonValues.statusNames.put(CommonValues.STATUS_PAUSE, "暂停使用");
		
		CommonValues.statusNames.put("y", "可用");
		CommonValues.statusNames.put("n", "不可用");

		CommonValues.userTypeNames.put(CommonValues.USER_TYPE_ADMIN, "管理员");
		CommonValues.userTypeNames.put(CommonValues.USER_TYPE_COMMON, "一般用户");
		
		CommonValues.isOrders.put("y", "是");
		CommonValues.isOrders.put("n", "否");
		
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_INQUEUE,"入队列");
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_OUTQUEUE,"出队列");
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_RUNNING,"运行中");
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_LOADED,"数据已加载");
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_TRANSFORMED,"数据已转换");
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_SUCCESS,"完成");
		CommonValues.taskStatusNames.put(CommonValues.TASK_STATUS_FAILED,"失败");
		
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_START, 1);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_STOP, 2);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_PAUSE, 3);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_ADD_NODE, 4);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_REMOVE_NODE, 5);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_DELETE, 6);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_UPLOAD_JAR, 7);
		CommonValues.clusterOperators.put(CommonValues.CLUSTER_MODIFY, 8);
		
		CommonValues.hadoopVersions.add("1");
		CommonValues.hadoopVersions.add("2");
		
		CommonValues.booleanNames.put("true","是");
		CommonValues.booleanNames.put("false","否");
		
		CommonValues.paramTypes.put(1, "下拉框");
		CommonValues.paramTypes.put(2, "输入框");

		CommonValues.dateFormats.add("");
		CommonValues.dateFormats.add("yyyy-mm-dd");
		CommonValues.dateFormats.add("yyyymmdd");
		
		CommonValues.initFlag = true;
	
	}
	
	public static void throwException(String error) throws Exception {

			throw new Exception(error);
	}
	
	@SuppressWarnings("unused")
	private void construct_dicts(Map<String, Map<String, String>> dicts) {
	
		List<Dict> dictList = DefaultImpl.getDicts();
		
		if (dictList == null ) return ;
		
		for (Dict dict : dictList){
			if (dicts.containsKey(dict.getDictName())){
				dicts.get(dict.getDictName()).put(dict.getDictKey(), dict.getDictValue());
			} else {
				Map<String,String> map = Maps.newHashMap();
				map.put(dict.getDictKey(), dict.getDictValue());
				dicts.put(dict.getDictName(), map);
			}
		}
		
	}

	public static String getHelloInfo(String userNo) {
		
		return "用户 ： "+ userNo + " !   登录时间：" + df.format(new Date());
	}
	
	public static String getUserNo(){

		return ((DilithiumSession)Session.get()).getUserNo();

	}
	
	private static String getFileName(String perfix , String id, String suffix){
		return perfix + "_" + id + suffix ;
	}
	
	public static String getDSTableFileName(String dsNo){
		return CommonValues.getFileName(CommonValues.DS_TABLE_PERFIX,dsNo,CommonValues.SCRIPT_SUFFIX);
	}

	public static String getDSLoadFileName(String dsNo){
		return CommonValues.getFileName(CommonValues.DS_LOAD_PERFIX, dsNo,CommonValues.SCRIPT_SUFFIX);
	}
	
	public static String getDSTransformFileName(String dsNo,String funcNo){
		return CommonValues.getFileName(CommonValues.DS_TRANSFORM_PERFIX, dsNo + "_" + funcNo,CommonValues.SCRIPT_SUFFIX);
	}
	
	public static String getFuncTableFileName(String funcNo){
		return CommonValues.getFileName(CommonValues.FUNC_TABLE_PERFIX,funcNo,CommonValues.SCRIPT_SUFFIX);
	}

	public static String getFuncHandlerFileName(String funcNo){
		return CommonValues.getFileName(CommonValues.FUNC_HANDLER_PERFIX, funcNo,CommonValues.SCRIPT_SUFFIX);
	}

	public static int getLimitRows() {
		// get limit rows
		int limit = CommonValues.DEFAULT_LIMIT_ROWS;
		try {
			limit = Integer.parseInt(CommonValues.props.get("limit_rows").toString());
		} catch (Exception e){	}
		return limit;
	}
	
	public static String getTempDir(){
		return CommonValues.props.getProperty("tempdir");
	}

	public static String getTaskLogFile(String cacheID){
		return "/tmp/cache_id_" + cacheID + ".log";
	}

}